/**
* @file        loc_signal_type
* @brief       
* @version     1.0.0
* @author      Changlin.Jing 
* @date        2023/7/27 11:16
* @copyright   Copyright  2022 Langge Software Co., Ltd. All rights reserved.
*/
#ifndef LANGGE_VDR_LOC_SIGNAL_TYPE_H
#define LANGGE_VDR_LOC_SIGNAL_TYPE_H
#include <memory>
enum LOC_TYPE {
    LOC_TYPE_UNKNOWN    = 0,     /// 0 - 默认值
    LOC_TYPE_GNSS       = 1,     /// 1 - 卫星定位
    LOC_TYPE_WIFI       = 5,     /// 5 - WIFI定位结果
    LOC_TYPE_CELL       = 6,     /// 6 - 基站定位结果
    LOC_TYPE_LOCAL_FILE = 9      /// 9 - 读取本地文件的前一次缓存结果
};
enum LOC_SIGNAL_TYPE {
    UNKNOWN_SIGNAL = 0,
    ACC_SIGNAL,
    GYRO_SIGNAL,
    MAGN_SIGNAL,
    ROTATION_SIGNAL,
    SATELLITE_SIGNAL,
    POS_SIGNAL,
    CAR_SIGNAL,
    FUSE_SIGNAL,
    SIGNAL_COUNT
};

// GPS卫星信息
struct SAT {
    int32_t m_iSVID;            // 卫星标识
    int32_t m_iType;            // 卫星类型 0 未知类型 1 GPS 2 SBAS 3 GLONASS 4 QZSS 5 BEIDOU 6 GALILEO 7 IRNSS
    double m_dAzimuth;          // 方位角
    double m_dSNR;              // 信噪比
    double m_dElevation;        // 仰角
    int32_t m_iSAvaliable = 0;  // 是否可用
};

// 信号基类
struct I_LOC_SIGNAL {
public:
    I_LOC_SIGNAL(std::int64_t ts, LOC_SIGNAL_TYPE type) {
        mLocalTickTime = ts;
        mLocalSignalType = type;
    }

    // 时间戳
    std::int64_t mLocalTickTime = 0L;
    LOC_SIGNAL_TYPE mLocalSignalType = UNKNOWN_SIGNAL;
};

struct LOC_ACC_SIGNAL : I_LOC_SIGNAL {
public:
    LOC_ACC_SIGNAL(long ts, float standx, float standy, float standz, float originx, float originy, float originz,
                   float timeGap = 0.f) : I_LOC_SIGNAL(ts, ACC_SIGNAL) {
        mStandX = standx;
        mStandY = standy;
        mStandZ = standz;
        mOriginX = originx;
        mOriginY = originy;
        mOriginZ = originz;
        mTimeGap = timeGap;
    };

    LOC_ACC_SIGNAL() : I_LOC_SIGNAL(0L, ACC_SIGNAL) {}

public:
    float mStandX{0};
    float mStandY{0};
    float mStandZ{0};
    float mOriginX{0};
    float mOriginY{0};
    float mOriginZ{0};
    float mTimeGap{0};
};

// 陀螺仪信号
struct LOC_GYRO_SIGNAL : I_LOC_SIGNAL {
public:
    LOC_GYRO_SIGNAL(long ts, float standx, float standy, float standz, float originx, float originy, float originz,
                    float timeGap = 0.f) : I_LOC_SIGNAL(ts, GYRO_SIGNAL) {
        mStandX = standx;
        mStandY = standy;
        mStandZ = standz;
        mOriginX = originx;
        mOriginY = originy;
        mOriginZ = originz;
        mTimeGap = timeGap;
    };

    LOC_GYRO_SIGNAL() : I_LOC_SIGNAL(0L, GYRO_SIGNAL) {}

public:
    float mStandX{0};
    float mStandY{0};
    float mStandZ{0};
    float mOriginX{0};
    float mOriginY{0};
    float mOriginZ{0};
    float mTimeGap{0};
};

// 磁力计信号
struct LOC_MAGN_SIGNAL : I_LOC_SIGNAL {
public:
    LOC_MAGN_SIGNAL(long ts, float standx, float standy, float standz, float originx, float originy, float originz,
                    float timeGap = 0.f) : I_LOC_SIGNAL(ts, MAGN_SIGNAL) {
        mStandX = standx;
        mStandY = standy;
        mStandZ = standz;
        mOriginX = originx;
        mOriginY = originy;
        mOriginZ = originz;
        mTimeGap = timeGap;
    };

    LOC_MAGN_SIGNAL() : I_LOC_SIGNAL(0L, MAGN_SIGNAL) {}

public:
    float mStandX{0};
    float mStandY{0};
    float mStandZ{0};
    float mOriginX{0};
    float mOriginY{0};
    float mOriginZ{0};
    float mTimeGap{0};
};

// 星历信息数组
struct LOC_SATELLITE_SIGNAL : public I_LOC_SIGNAL {
public:
    LOC_SATELLITE_SIGNAL() : I_LOC_SIGNAL(0L, SATELLITE_SIGNAL) {};
    int32_t m_iTotal{};                                                  // 卫星总数
    int32_t m_iAvailableCount{};                                         // 有效卫星数量（最多12）
    SAT m_aSat[50]{};                                                    // 卫星信息数组，最多容纳12颗卫星信息
    char m_aMagicNumber[8] = {'A', 'S', 'A', 'T', 'a', 's', 'a', 't'}; // 幻数数据验证用
};


struct LOC_ROTATION_SIGNAL : public I_LOC_SIGNAL {
public:
    LOC_ROTATION_SIGNAL(std::uint64_t ts, float x, float y, float z) : I_LOC_SIGNAL(ts, ROTATION_SIGNAL) {
        mX = x;
        mY = y;
        mZ = z;
    }

    float mRotation[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};

    LOC_ROTATION_SIGNAL() : I_LOC_SIGNAL(0L, ROTATION_SIGNAL) {}

public:
    float mX{};
    float mY{};
    float mZ{};
};

struct LOC_CAR_SIGNAL : public I_LOC_SIGNAL {
public:
    //此时间主要时用于与GPS时间计算时间差，估计延时
    int64_t mCarTimestamp{-1};
    // 补偿后纵向速度 default: -1; range: +-40  unit:m/s; 备份名： mVelLgtCompensated
    float mRealSpeed{-1.f};
    //时间间隔，ms
    float mTimeGap{0};

    LOC_CAR_SIGNAL(std::uint64_t ts, std::uint64_t carTime, float realSpeed, float timeGap = 0.f) : I_LOC_SIGNAL(ts,
                                                                                                                 CAR_SIGNAL) {
        mCarTimestamp = carTime;
        mRealSpeed = realSpeed;
        mTimeGap = timeGap;
    }

    LOC_CAR_SIGNAL() : I_LOC_SIGNAL(0L, CAR_SIGNAL) {}

    //时间有效&&速度在0~140km/h之间
    // 注意到车机上未接车速默认输出的速度试0.0 这个有效性判断暂时处理不了
    bool isSpeedValid() {
        return mLocalTickTime > 0 && mRealSpeed >= 0 && mRealSpeed < 40;
    }

};

struct LOC_POS_SIGNAL : public I_LOC_SIGNAL {
public:
    explicit LOC_POS_SIGNAL(int64_t ts) : I_LOC_SIGNAL(ts, POS_SIGNAL) {
        init();
    }

    LOC_POS_SIGNAL() : I_LOC_SIGNAL(0L, POS_SIGNAL) {}

    void init() {
        mSpeed = 0.0f;
        mHeading = 0.0f;
        mHeight = 0.0f;
        mValidSatCount = -1;
        mAccuracyLocHorizoon = 0.0f;
        mAccuracyLocVertical = 0.0f;
        mAccuracyVelocity = 0.0f;
        mAccuracyAngularVelocity = 0.0f;
        mLonLatSrc = 0;
        mSpeedSrc = 0;
        mPitch = 0.f;
        mRoll = 0.f;
        mYawDiff = 361.f;
    }


    std::int64_t mUtcTickTime = 0;
    double mLatitude{};
    double mLongitude{};
    /*速度 单位 km/h*/
    double mSpeed{};
    /*朝向 东零 逆时针*/
    double mHeading{};

    double mHeight{};

    std::int32_t mValidSatCount{};
    /// 位置水平精度
    double mAccuracyLocHorizoon{};
    /// 位置垂直精度
    double mAccuracyLocVertical{};
    /// 速度精度
    double mAccuracyVelocity{};
    /// 角速度精度
    double mAccuracyAngularVelocity{};

    LOC_TYPE mLocType = LOC_TYPE_UNKNOWN;
    /// 补充 LOC_TYPE_FUSION 字段
    int mLonLatSrc{};
    //速度来源
    int mSpeedSrc{};
    //pitch
    float mPitch{};
    //roll
    float mRoll{};
    //角度变化
    float mYawDiff{};
    //信息有效判断
    bool isValid() {
        return mLocalTickTime > 0 && mLocType > LOC_TYPE_UNKNOWN;
    }
    bool isLonLatValid() {
        return mLocalTickTime > 0 && mLatitude > 0 && mLongitude > 0;
    }
};
#endif //LANGGE_VDR_LOC_SIGNAL_TYPE_H
